package com.gaoxk.asserviceinterceptor;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.cxf.phase.Phase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.namespace.QName;
import java.util.List;

/**
 * CXF拦截器：检测请求的服务是否存在
 */
public class ServiceExistenceInterceptor extends AbstractSoapInterceptor {
    private static final Logger log = LoggerFactory.getLogger(ServiceExistenceInterceptor.class);

    public ServiceExistenceInterceptor() {
        // 在协议处理前拦截，此时已解析SOAP目标信息但未执行业务逻辑
        super(Phase.PRE_PROTOCOL);
    }

    @Override
    public void handleMessage(SoapMessage message) throws Fault {
        try {
            // 1. 获取当前请求的目标服务QName（服务名+命名空间）
            QName targetServiceQName = getTargetServiceQName(message);
            if (targetServiceQName == null) {
                throw new Fault(new IllegalArgumentException("请求中未包含有效的服务标识"));
            }

            // 2. 获取当前CXF发布的所有服务信息
            Endpoint endpoint = message.getExchange().getEndpoint();
            List<ServiceInfo> publishedServices = endpoint.getService().getServiceInfos();

            // 3. 检查目标服务是否在已发布服务列表中
            boolean serviceExists = publishedServices.stream()
                    .anyMatch(serviceInfo -> targetServiceQName.equals(serviceInfo.getName()));

            // 4. 若服务不存在，抛出SOAP错误
            if (!serviceExists) {
                log.warn("请求的服务不存在: {}", targetServiceQName);
                Fault fault = new Fault(
                        new Exception("请求的服务不存在: " + targetServiceQName),
                        new QName("http://schemas.xmlsoap.org/soap/envelope/", "Client", "soap")
                );
                throw fault;
            }

        } catch (Fault e) {
            throw e; // 直接抛出已包装的SOAP错误
        } catch (Exception e) {
            // 处理其他异常
            throw new Fault(new Exception("服务检测失败: " + e.getMessage(), e));
        }
    }

    /**
     * 从SOAP消息中解析目标服务的QName（服务名+命名空间）
     */
    private QName getTargetServiceQName(SoapMessage message) {
        // 方式1：从SOAPAction中解析（适用于通过SOAPAction指定服务的场景）
//        String soapAction = (String) message.get(SoapMessage.SOAP_ACTION);
//        if (soapAction != null && !soapAction.isEmpty()) {
//            return parseQNameFromSoapAction(soapAction);
//        }

        // 方式2：从消息交换的目标服务信息中获取（更通用）
        Endpoint endpoint = message.getExchange().getEndpoint();
        if (endpoint != null && endpoint.getService() != null) {
            return endpoint.getService().getName();
        }

        // 方式3：从SOAP信封的目标命名空间解析（作为 fallback）
        String targetNamespace = message.getVersion().getEnvelope().getNamespaceURI();
        if (targetNamespace != null) {
            // 实际场景中可能需要结合本地名解析，此处简化处理
            return new QName(targetNamespace, "UnknownService");
        }

        return null;
    }

    /**
     * 从SOAPAction中解析服务QName（SOAPAction格式通常为"命名空间#服务名"）
     */
    private QName parseQNameFromSoapAction(String soapAction) {
        try {
            // 移除可能的引号
            String action = soapAction.replace("\"", "");
            int separatorIndex = action.lastIndexOf('#');
            if (separatorIndex > 0 && separatorIndex < action.length() - 1) {
                String namespace = action.substring(0, separatorIndex);
                String localPart = action.substring(separatorIndex + 1);
                return new QName(namespace, localPart);
            }
        } catch (Exception e) {
            log.warn("解析SOAPAction失败: {}", soapAction, e);
        }
        return null;
    }
}
